package com.xjc.business.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xjc.business.entity.domain.*;
import com.xjc.business.entity.po.buildadmin.*;
import com.xjc.business.entity.vo.buildadmin.BuildDetailsVo;
import com.xjc.business.entity.vo.buildadmin.CheckBedNotAddRoomVo;
import com.xjc.business.entity.vo.buildadmin.CheckBedVo;
import com.xjc.business.service.*;
import com.xjc.business.mapper.CheckBedBatchMapper;
import com.xjc.system.constants.MyConstants;
import com.xjc.system.result.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
* @author root
* @description 针对表【check_bed_batch(查寝批次)】的数据库操作Service实现
* @createDate 2025-03-08 17:07:50
*/
@Service
public class CheckBedBatchServiceImpl extends ServiceImpl<CheckBedBatchMapper, CheckBedBatch>
    implements CheckBedBatchService{

    @Autowired
    @Lazy
    CheckBedRoomService checkBedRoomService;

    @Autowired
    @Lazy
    CheckBedStudentService checkBedStudentService;

    @Autowired
    @Lazy
    DormitoriesService dormitoriesService;

    @Autowired
    @Lazy
    BedsService bedsService;

    @Autowired
    @Lazy
    AllStudentRegsiterRelationsService allStudentRegsiterRelationsService;

    @Autowired
    @Lazy
    AllStudentStayRelationsService allStudentStayRelationsService;

    @Autowired
    @Lazy
    CollegesService collegesService;

    @Autowired
    @Lazy
    MajorsService majorsService;

    @Autowired
    @Lazy
    ClazzsService clazzsService;

    @Autowired
    @Lazy
    StudentsService studentsService;

    @Autowired
    @Lazy
    BuildingAdminRelationsService buildingAdminRelationsService;

    @Autowired
    @Lazy
    DormitoryBedRelationsService dormitoryBedRelationsService;

    @Autowired
    @Lazy
    BuildingsService buildingsService;

    @Autowired
    @Lazy
    CheckBedBackService checkBedBackService;

    @Autowired
    @Lazy
    CheckBedBackStudentService checkBedBackStudentService;

    /**
     * 获取当前检查宿舍信息
     * @param id 宿管id
     * @return
     */
    @Override
    public Result<CheckBedVo> getCurrentCheckBed(Integer id) {
        LambdaQueryWrapper<CheckBedBatch> checkBedBatchLambdaQueryWrapper= new LambdaQueryWrapper<>();
        checkBedBatchLambdaQueryWrapper.eq(CheckBedBatch::getBuildAdminId,id);
        checkBedBatchLambdaQueryWrapper.eq(CheckBedBatch::getStatus,1);
        CheckBedBatch checkBedBatch = getOne(checkBedBatchLambdaQueryWrapper);
        if(checkBedBatch == null){
            return Result.okWithData(null);
        }

        CheckBedVo checkBedVo = new CheckBedVo();

        checkBedVo.setId(checkBedBatch.getId());
        checkBedVo.setNum(checkBedBatch.getNum());
        checkBedVo.setTypeOne(MyConstants.CHECK_BED_TYPE_ONE.get(checkBedBatch.getTypeOne()));
        checkBedVo.setTypeTwo(MyConstants.CHECK_BED_TYPE_TWO.get(checkBedBatch.getTypeTwo()));
        checkBedVo.setDescInfo(checkBedBatch.getDescInfo());
        checkBedVo.setStartTime(checkBedBatch.getStartTime());

        LambdaQueryWrapper<CheckBedRoom> checkBedRoomLambdaQueryWrapper = new LambdaQueryWrapper<>();
        checkBedRoomLambdaQueryWrapper.eq(CheckBedRoom::getBatchId,checkBedBatch.getId());
        checkBedRoomLambdaQueryWrapper.orderByAsc(CheckBedRoom::getDormitoryId);

        List<CheckBedVo.CheckBedRoomVo> checkBedRoomVoList = checkBedRoomService.list(checkBedRoomLambdaQueryWrapper).stream().map(checkBedRoom -> {
            CheckBedVo.CheckBedRoomVo checkBedRoomVo = new CheckBedVo.CheckBedRoomVo();
            checkBedRoomVo.setId(checkBedRoom.getId());
            Integer dormitoryId = checkBedRoom.getDormitoryId();
            checkBedRoomVo.setDormitoryNum(dormitoriesService.getById(dormitoryId).getDno()+"");
            checkBedRoomVo.setNum(checkBedRoom.getNum());

            LambdaQueryWrapper<CheckBedStudent> checkBedStudentLambdaQueryWrapper = new LambdaQueryWrapper<>();
            checkBedStudentLambdaQueryWrapper.eq(CheckBedStudent::getRoomId,checkBedRoom.getId());
            checkBedStudentLambdaQueryWrapper.orderByAsc(CheckBedStudent::getBedId);
            List<CheckBedVo.CheckBedStudentVo> checkBedStudentVoList = checkBedStudentService.list(checkBedStudentLambdaQueryWrapper).stream().map(checkBedStudent -> {
                CheckBedVo.CheckBedStudentVo checkBedStudentVo = new CheckBedVo.CheckBedStudentVo();
                checkBedStudentVo.setId(checkBedStudent.getId());
                checkBedStudentVo.setBedNum(bedsService.getById(checkBedStudent.getBedId()).getBno()+"");
                Integer stuId = checkBedStudent.getStuId();
                LambdaQueryWrapper<AllStudentRegsiterRelations> allStudentRegsiterRelationsLambdaQueryWrapper = new LambdaQueryWrapper<>();
                allStudentRegsiterRelationsLambdaQueryWrapper.eq(AllStudentRegsiterRelations::getStuId,stuId);
                AllStudentRegsiterRelations studentFromDB = allStudentRegsiterRelationsService.getOne(allStudentRegsiterRelationsLambdaQueryWrapper);
                Integer colId = studentFromDB.getColId();
                Integer majId = studentFromDB.getMajId();
                Integer clazzId = studentFromDB.getClazzId();
                checkBedStudentVo.setStuInfo(collegesService.getById(colId).getName()+" "+majorsService.getById(majId).getName()+"专业 "+clazzsService.getById(clazzId).getNum()+"班 "+studentsService.getById(stuId).getName());

                return checkBedStudentVo;
            }).collect(Collectors.toList());

            checkBedRoomVo.setCheckBedStudentVoList(checkBedStudentVoList);

            return checkBedRoomVo;
        }).collect(Collectors.toList());

        checkBedVo.setCheckBedRoomVoList(checkBedRoomVoList);
        return Result.okWithData(checkBedVo);
    }

    /**
     * 添加检查宿舍信息
     * @param checkBedPo 检查宿舍信息
     * @return
     */
    @Override
    public Result<String> addCheckBed(CheckBedPo checkBedPo) {
        Integer id = checkBedPo.getId();
        Integer typeOne = checkBedPo.getTypeOne();
        Integer typeTwo = checkBedPo.getTypeTwo();
        String descInfo = checkBedPo.getDescInfo();

        CheckBedBatch checkBedBatch = new CheckBedBatch();
        LambdaQueryWrapper<BuildingAdminRelations> buildingAdminRelationsLambdaQueryWrapper = new LambdaQueryWrapper<>();
        buildingAdminRelationsLambdaQueryWrapper.eq(BuildingAdminRelations::getBuildAdminId,id);
        Integer buildId = buildingAdminRelationsService.getOne(buildingAdminRelationsLambdaQueryWrapper).getBuildId();

        checkBedBatch.setBuildId(buildId);
        checkBedBatch.setBuildAdminId(id);
        checkBedBatch.setNum(0);
        checkBedBatch.setTypeOne(typeOne);
        checkBedBatch.setTypeTwo(typeTwo);
        checkBedBatch.setDescInfo(descInfo);
        checkBedBatch.setStatus(1);
        checkBedBatch.setStartTime(new Date());
        save(checkBedBatch);
        return Result.okWithData("添加成功");
    }

    /**
     * 添加宿舍项
     * @param checkBedRoomPo 宿舍项信息
     * @return
     */
    @Override
    public Result<String> addCheckBedRoom(CheckBedRoomPo checkBedRoomPo) {
        CheckBedRoom checkBedRoom = new CheckBedRoom();
        checkBedRoom.setBatchId(checkBedRoomPo.getBatchId());
        checkBedRoom.setDormitoryId(checkBedRoomPo.getDormitoryId());
        checkBedRoom.setNum(0);
        checkBedRoomService.save(checkBedRoom);
        return Result.okWithData("添加成功");
    }

    /**
     * 删除检查宿舍信息
     * @param id 检查宿舍信息id
     * @return
     */
    @Override
    @Transactional
    public Result<String> deleteCheckBed(Integer id) {
        LambdaQueryWrapper<CheckBedRoom> checkBedRoomLambdaQueryWrapper = new LambdaQueryWrapper<>();
        checkBedRoomLambdaQueryWrapper.eq(CheckBedRoom::getBatchId,id);
        List<Integer> checkBedRoomIdList = checkBedRoomService.list(checkBedRoomLambdaQueryWrapper).stream().map(CheckBedRoom::getId).collect(Collectors.toList());

        if(!checkBedRoomIdList.isEmpty()){
            LambdaQueryWrapper<CheckBedStudent> checkBedStudentLambdaQueryWrapper = new LambdaQueryWrapper<>();
            checkBedStudentLambdaQueryWrapper.in(CheckBedStudent::getRoomId,checkBedRoomIdList);
            checkBedStudentService.remove(checkBedStudentLambdaQueryWrapper);
        }
        checkBedRoomService.remove(checkBedRoomLambdaQueryWrapper);

        removeById(id);
        return Result.okWithData("删除成功");
    }

    /**
     * 删除宿舍项
     * @param checkBedDeletePo 宿舍项id
     * @return
     */
    @Override
    @Transactional
    public Result<String> deleteCheckBedRoom(Integer batchId,Integer roomId) {
        LambdaQueryWrapper<CheckBedStudent> checkBedStudentLambdaQueryWrapper = new LambdaQueryWrapper<>();
        checkBedStudentLambdaQueryWrapper.in(CheckBedStudent::getRoomId,roomId);
        long count = checkBedStudentService.count(checkBedStudentLambdaQueryWrapper);
        checkBedStudentService.remove(checkBedStudentLambdaQueryWrapper);

        checkBedRoomService.removeById(roomId);

        CheckBedBatch bedBatch = getById(batchId);
        bedBatch.setNum((int) (bedBatch.getNum()-count));
        updateById(bedBatch);

        return Result.okWithData("删除成功");
    }

    /**
     * 添加宿舍项学生
     * @param checkBedStudentPo
     * @return
     */
    @Override
    @Transactional
    public Result<String> addCheckBedStudent(CheckBedStudentPo checkBedStudentPo) {
        Integer roomId = checkBedStudentPo.getRoomId();
        CheckBedRoom checkBedRoom = checkBedRoomService.getById(roomId);
        Integer bedNo = checkBedStudentPo.getBedNo();
        LambdaQueryWrapper<DormitoryBedRelations> dormitoryBedRelationsLambdaQueryWrapper = new LambdaQueryWrapper<>();
        dormitoryBedRelationsLambdaQueryWrapper.eq(DormitoryBedRelations::getDid,checkBedRoom.getDormitoryId());
        List<Integer> bedIdList = dormitoryBedRelationsService.list(dormitoryBedRelationsLambdaQueryWrapper).stream().map(DormitoryBedRelations::getBedid).collect(Collectors.toList());

        LambdaQueryWrapper<Beds> bedsLambdaQueryWrapper = new LambdaQueryWrapper<>();
        bedsLambdaQueryWrapper.eq(Beds::getBno,bedNo);
        bedsLambdaQueryWrapper.in(Beds::getId,bedIdList);
        Beds beds = bedsService.getOne(bedsLambdaQueryWrapper);
        Integer bedsId = beds.getId();

        CheckBedStudent checkBedStudent = new CheckBedStudent();
        checkBedStudent.setRoomId(roomId);
        checkBedStudent.setBedId(bedsId);

        LambdaQueryWrapper<AllStudentStayRelations> allStudentStayRelationsLambdaQueryWrapper = new LambdaQueryWrapper<>();
        allStudentStayRelationsLambdaQueryWrapper.eq(AllStudentStayRelations::getBedId,bedsId);
        AllStudentStayRelations allStudentStayRelations = allStudentStayRelationsService.getOne(allStudentStayRelationsLambdaQueryWrapper);
        Integer stuId = allStudentStayRelations.getStuId();
        checkBedStudent.setStuId(stuId);

        LambdaQueryWrapper<AllStudentRegsiterRelations> allStudentRegsiterRelationsLambdaQueryWrapper = new LambdaQueryWrapper<>();
        allStudentRegsiterRelationsLambdaQueryWrapper.eq(AllStudentRegsiterRelations::getStuId,stuId);
        AllStudentRegsiterRelations allStudentRegsiterRelations = allStudentRegsiterRelationsService.getOne(allStudentRegsiterRelationsLambdaQueryWrapper);
        Integer collegeId = allStudentRegsiterRelations.getColId();
        checkBedStudent.setCollegeId(collegeId);

        checkBedStudentService.save(checkBedStudent);

        checkBedRoom.setNum(checkBedRoom.getNum()+1);
        checkBedRoomService.updateById(checkBedRoom);

        Integer batchId = checkBedStudentPo.getBatchId();
        CheckBedBatch bedBatch = getById(batchId);
        bedBatch.setNum(bedBatch.getNum()+1);
        updateById(bedBatch);

        return Result.okWithData("添加成功");
    }

    /**
     * 删除宿舍项学生
     * @return
     */
    @Override
    @Transactional
    public Result<String> deleteCheckBedStudent(Integer batchId,Integer id) {
        Integer roomId = checkBedStudentService.getById(id).getRoomId();

        CheckBedRoom checkBedRoom = checkBedRoomService.getById(roomId);
        checkBedRoom.setNum(checkBedRoom.getNum()-1);
        checkBedRoomService.updateById(checkBedRoom);

        checkBedStudentService.removeById(id);

        CheckBedBatch bedBatch = getById(batchId);
        bedBatch.setNum(bedBatch.getNum() - 1);
        updateById(bedBatch);
        return Result.okWithData("删除成功");
    }

    /**
     * 获取当前宿舍楼宿舍列表
     * @return
     */
    @Override
    public Result<List<CheckBedNotAddRoomVo>> getBuildDormitoryList(Integer buildingAdminId) {
        
        LambdaQueryWrapper<BuildingAdminRelations> buildingAdminRelationsLambdaQueryWrapper = new LambdaQueryWrapper<>();
        buildingAdminRelationsLambdaQueryWrapper.eq(BuildingAdminRelations::getBuildAdminId,buildingAdminId);
        BuildingAdminRelations buildingAdminRelations = buildingAdminRelationsService.getOne(buildingAdminRelationsLambdaQueryWrapper);
        Integer buildingId = buildingAdminRelations.getBuildId();
        // 已被选宿舍列表
        List<Integer> hasAddRoomIdList = new ArrayList<>();

        LambdaQueryWrapper<CheckBedBatch> checkBedBatchLambdaQueryWrapper = new LambdaQueryWrapper<>();
        checkBedBatchLambdaQueryWrapper.eq(CheckBedBatch::getBuildId,buildingId);
        List<Integer> batchIdList = list(checkBedBatchLambdaQueryWrapper).stream().map(CheckBedBatch::getId).collect(Collectors.toList());
        if(!batchIdList.isEmpty()){
            LambdaQueryWrapper<CheckBedRoom> checkBedRoomLambdaQueryWrapper = new LambdaQueryWrapper<>();
            checkBedRoomLambdaQueryWrapper.in(CheckBedRoom::getBatchId,batchIdList);
            hasAddRoomIdList = checkBedRoomService.list(checkBedRoomLambdaQueryWrapper).stream().map(CheckBedRoom::getDormitoryId).collect(Collectors.toList());
        }

        // 去除“已被选宿舍床位列表”之外的宿舍列表
        List<CheckBedNotAddRoomVo> buildDetailsVoList =buildingsService.getBuildDormitoryListWithCheckBed(buildingId,hasAddRoomIdList);

        return Result.okWithData(buildDetailsVoList);
    }

    /**
     * 宿舍检查完成
     * @param id 宿舍检查id
     * @return
     */
    @Override
    public Result<String> finishCheckBed(Integer id) {
        CheckBedBatch bedBatch = getById(id);
        if(bedBatch.getNum() == 0){
            return Result.ok("不含查寝内容，请直接删除");
        }
        bedBatch.setStatus(0);
        bedBatch.setEndTime(new Date());
        updateById(bedBatch);
        return Result.okWithData("结束成功");
    }

    /**
     * 上传检查结果
     * @param id 宿舍检查id
     * @return
     */
    @Override
    public Result<String> reportCheckBedResult(Integer id) {
        CheckBedBatch bedBatch = getById(id);
        if (bedBatch.getStatus() == 1){
            return Result.ok("请在结束后上传");
        }

        LambdaQueryWrapper<CheckBedRoom> checkBedRoomLambdaQueryWrapper = new LambdaQueryWrapper<>();
        checkBedRoomLambdaQueryWrapper.eq(CheckBedRoom::getBatchId,id);
        Map<Integer,List<Integer>> stuMap = new HashMap<>();

        checkBedRoomService.list(checkBedRoomLambdaQueryWrapper).forEach(checkBedRoom -> {
            Integer roomId = checkBedRoom.getId();
            LambdaQueryWrapper<CheckBedStudent> checkBedStudentLambdaQueryWrapper = new LambdaQueryWrapper<>();
            checkBedStudentLambdaQueryWrapper.eq(CheckBedStudent::getRoomId,roomId);
            checkBedStudentService.list(checkBedStudentLambdaQueryWrapper).forEach(checkBedStudent -> {
                Integer stuId = checkBedStudent.getStuId();
                Integer collegeId = checkBedStudent.getCollegeId();
                if(stuMap.containsKey(collegeId)){
                    stuMap.get(collegeId).add(stuId);
                } else {
                    List<Integer> stuIdList = new ArrayList<>();
                    stuIdList.add(stuId);
                    stuMap.put(collegeId,stuIdList);
                }
            });
        });

        if(stuMap.isEmpty()){
            return Result.ok("查寝内容为空");
        }

        Integer typeOne = bedBatch.getTypeOne();
        Integer typeTwo = bedBatch.getTypeTwo();
        Date startTime = bedBatch.getStartTime();

        // 创建Calendar实例并设置时间为原始Date
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startTime);

        // 获取年、月、日
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH); // 注意：月份是从0开始的
        int day = calendar.get(Calendar.DAY_OF_MONTH);

        Calendar newCalendar = Calendar.getInstance();
        newCalendar.clear(); // 清除所有字段，避免时间部分不为0
        newCalendar.set(year, month, day);


        Date newStartTime = newCalendar.getTime();

        for (Map.Entry<Integer, List<Integer>> stuEntity : stuMap.entrySet()) {
            Integer collegeId = stuEntity.getKey();
            List<Integer> stuIdList = stuEntity.getValue();

            LambdaQueryWrapper<CheckBedBack> checkBedBackLambdaQueryWrapper = new LambdaQueryWrapper<>();
            checkBedBackLambdaQueryWrapper.eq(CheckBedBack::getCollegeId,collegeId);
            checkBedBackLambdaQueryWrapper.eq(CheckBedBack::getTypeOne,typeOne);
            checkBedBackLambdaQueryWrapper.eq(CheckBedBack::getTypeTwo,typeTwo);
            checkBedBackLambdaQueryWrapper.eq(CheckBedBack::getStartTime,newStartTime);

            CheckBedBack checkBedBackFromDb = checkBedBackService.getOne(checkBedBackLambdaQueryWrapper);

            if(checkBedBackFromDb == null){
                checkBedBackFromDb = new CheckBedBack();
                checkBedBackFromDb.setCollegeId(collegeId);
                checkBedBackFromDb.setTypeOne(typeOne);
                checkBedBackFromDb.setTypeTwo(typeTwo);
                checkBedBackFromDb.setStartTime(newStartTime);
                checkBedBackFromDb.setDescInfo(bedBatch.getDescInfo());
                checkBedBackFromDb.setEndTime(newStartTime);

                checkBedBackService.save(checkBedBackFromDb);
            }

            List<CheckBedBackStudent> checkBedBackStudentList = new ArrayList<>();
            for (Integer stuId: stuIdList) {
                LambdaQueryWrapper<AllStudentRegsiterRelations> allStudentRegsiterRelationsLambdaQueryWrapper = new LambdaQueryWrapper<>();
                allStudentRegsiterRelationsLambdaQueryWrapper.eq(AllStudentRegsiterRelations::getStuId,stuId);
                AllStudentRegsiterRelations studentFromDB = allStudentRegsiterRelationsService.getOne(allStudentRegsiterRelationsLambdaQueryWrapper);
                Integer clazzId = studentFromDB.getClazzId();
                Integer majId = studentFromDB.getMajId();

                CheckBedBackStudent checkBedBackStudent = new CheckBedBackStudent();
                checkBedBackStudent.setBackId(checkBedBackFromDb.getId());
                checkBedBackStudent.setMajId(majId);
                checkBedBackStudent.setClassId(clazzId);
                checkBedBackStudent.setStuId(stuId);
                checkBedBackStudentList.add(checkBedBackStudent);
            }
            checkBedBackStudentService.saveBatch(checkBedBackStudentList);
        }

        return Result.okWithData("上传成功");
    }

    /**
     * 获取宿舍检查历史记录
     * @param id 宿管id
     * @return
     */
    @Override
    public Result<List<CheckBedVo>> getCheckBedHistoryList(Integer id) {
        LambdaQueryWrapper<CheckBedBatch> checkBedBatchLambdaQueryWrapper= new LambdaQueryWrapper<>();
        checkBedBatchLambdaQueryWrapper.eq(CheckBedBatch::getBuildAdminId,id);
        checkBedBatchLambdaQueryWrapper.eq(CheckBedBatch::getStatus,0);
        List<CheckBedVo> checkBedVoList = list(checkBedBatchLambdaQueryWrapper).stream().map(checkBedBatch -> {
            CheckBedVo checkBedVo = new CheckBedVo();
            checkBedVo.setId(checkBedBatch.getId());
            checkBedVo.setNum(checkBedBatch.getNum());
            checkBedVo.setTypeOne(MyConstants.CHECK_BED_TYPE_ONE.get(checkBedBatch.getTypeOne()));
            checkBedVo.setTypeTwo(MyConstants.CHECK_BED_TYPE_TWO.get(checkBedBatch.getTypeTwo()));
            checkBedVo.setDescInfo(checkBedBatch.getDescInfo());
            checkBedVo.setStartTime(checkBedBatch.getStartTime());

            return checkBedVo;
        }).collect(Collectors.toList());

        return Result.okWithData(checkBedVoList);
    }
}